home *** CD-ROM | disk | FTP | other *** search
-
-
- Anhang
-
- zur Dokumentation von TOY Prolog ST, Version 3
-
- Inhalt
-
- A.1 Aufbau des Interpreters
- A.2 Syntax des inneren Interpreters
- A.3 Die Systemdatei
- A.4 Die Implementierung der Benutzerschnittstelle
- A.5 Erweiterungen in der vorliegenden Version von TOY Prolog ST
- in Bezug auf die Dokumentation.
-
-
- A.1 Der Aufbau des Interpreters
-
- TOY Prolog besteht aus zwei Teilen, dem inneren und dem äußeren
- Interpreter. Der innere Interpreter ist in C und 68000-Assembler
- geschrieben, der äußere bereits in Prolog selbst. Der Vorteil an
- einer derartigen Implementierung ist, daß viele Teile des
- Interpreters in Prolog erheblich leichter zu formulieren sind als
- in anderen Programmiersprachen.
-
- Ein Beispiel dafür ist das Prädikat 'repeat'. In Prolog ist es wie
- folgt definiert :
-
- repeat.
- repeat :- repeat.
-
- Eine Implementierung von 'repeat' in C würde erfordern, die
- Datenstrukturen, die der innere Interpreter verwendet, zu
- erweitern; der entstehende Mehraufwand wäre beträchtlich.
-
- Die verwendete Technik hat natürlich auch Nachteile. Der größte
- davon ist zweifelsohne der der geringeren Geschwindigkeit. Der
- gesamte Parser von TOY Prolog ist im äußeren Interpreter
- implementiert, und aufgrund der komplexen Syntax (TOY Prolog soll
- weitgehend mit Prolog-10 kompatibel sein) ist der Parser sehr
- aufwendig. Man merkt das besonders schmerzlich beim Einlesen von
- Dateien mit 'consult' etc.
-
- Die geringe Geschwindigkeit beim Einlesen von Programmen kann man
- auf eine einfache Weise umgehen. Sobald man ein korrektes Programm
- vorliegen hat, kann man es in die Syntax des inneren Interpreters
- übersetzen. Die Geschwindigkeit, mit der derartige Zwischencodes
- eingelesen werden, übertrifft bei weitem die Lesegeschwindigkeit
- des äußeren Interpreters.
-
-
- Der äußere Interpreter besteht im wesentlichen aus einer
- Programmschleife (loop / 0), die Terme mit 'read' einliest und sie
- auswertet. Diese Schleife kann auch aus Benutzerprogrammen mit
-
- tag(loop)
-
- aufgerufen werden; sie wird durch das Prädikat 'stop' abgebrochen.
- Diese Möglichkeit wird z.B. im Editor verwendet.
-
- Die Art und Weise der Implementierung verlangt, daß der äußere
- Interpreter nach dem Programmstart eingelesen wird. Deshalb gibt
- es in TOY Prolog eine Systemdatei namens 'SYSFILE.TOY'. Sie
- enthält außer dem Zwischencode des äußeren Interpreters noch
- andere wichtige Daten, insbesondere die Namen und Stelligkeiten
- der Systemfunktionen und die Definitionen der vordefinierten
- Prädikate. Der Aufbau der Systemdatei wird in Abschnitt A.3
- erläutert.
-
-
- A.2 Die Syntax des inneren Interpreters
-
- Die Syntaxbeschreibung erfolgt analog zur Beschreibung der vollen
- Syntax in Abschnitt II.
-
- Klausel ::= Regel | Ziel
- Regel ::= F_Term : Aufrufliste
- Ziel ::= : Aufrufliste #
- Aufrufliste ::= { Aufruf . } []
- Aufruf ::= F_Term
-
- F_Term ::= Funktor | Funktor ( Argumente )
- Funktor ::= Name | Q_Name | [] | !
- Argumente ::= Term { , Term }
- Term ::= ( Term ) | Variable | Zahl | F_Term |
- Term . Term
- Variable ::= Anonyme_Variable | Numerierte_Variable
- Anonyme_Variable ::= _
- Numerierte_Variable ::= : Zahl
-
- Zahl ::= Vorzeichen Ziffer { Ziffer }
- Name ::= Kleinbuchstabe { Alphanumerisch }
- Q_Name ::= ' Q_Zeichen { Q_Zeichen } '
- Q_Zeichen ::= '' | Nicht_'
- *** Nicht_' ist jedes Zeichen außer '
- Alphanumerisch ::= Kleinbuchstabe | Großbuchstabe |
- Ziffer | _
- Vorzeichen ::= + | | -
- *** Das Vorzeichen kann auch fehlen.
- *** Kleinbuchstabe, Großbuchstabe, Ziffer siehe Abschnitt II.
-
-
- Erläuterungen
-
- (1) Der innere Interpreter liest nur Regeln und Ziele ein, wobei
- ein Ziel syntaktisch eine Regel ohne Kopf ist. Fakten müssen
- als Regeln repräsentiert werden, bei denen die Aufrufliste
- gleich [] ist. Ein Ziel wird durch das Zeichen '#' beendet,
- das dem Interpreter mitteilt, daß er mit der Auswertung des
- Ziels (d.h. mit dem Versuch, das Ziel zu erfüllen) beginnen
- soll. Es wird keine Meldung über Gelingen oder Fehlschlagen
- des Ziels ausgegeben.
-
- (2) Soll der innere Interpreter vom Datenstrom 'user' lesen, so
- verhält er sich, als habe er das Ziel
-
- : ear . [] #
-
- eingelesen. Dieses Ziel ist der Aufruf des äußeren
- Interpreters und muß daher als Prädikat vorhanden sein; für
- den Fall, daß ein anderes Prädikat als 'ear' in der
- Systemdatei (siehe Abschnitt A.3) eingetragen wurde, gilt
- sinngemäß dasselbe.
-
- (3) Anonyme Variablen, die der innere Interpreter einliest,
- verhalten sich anders als anonyme Variablen, die vom äußeren
- Interpreter eingelesen werden. Der innere Interpreter erzeugt
- 'echte' anonyme Variablen, die nicht mit Werten instantiiert
- werden können. Der äußere Interpreter erzeugt statt dessen
- einmalige Instanzen von 'normalen' Variablen. Der Unterschied
- ist normalerweise bedeutungslos; man sollte sich aber nicht
- darauf verlassen, daß z.B. 'numbervars' wirklich alle
- Variablen instantiiert.
-
- (4) Beim Einlesen von 'numerierten' Variablen erzeugt der innere
- Interpreter eine Tabelle, anhand derer er erkennt, wieviele
- verschiedene Variablen ein Term enthält. Der Term
-
- f( :1, :100)
-
- erfordert also nicht 100, sondern nur 2 Variablen. Die einer
- Variablen bei der Eingabe zugeordnete Nummer hat nichts mit
- der von 'display' oder 'write' ausgegebenen Variablennummer
- zu tun; 'display' benutzt die interne Repräsentation von
- Variablen, 'write' deren Reihenfolge im Term.
-
-
- A.3 Die Systemdatei
-
- Die Systemdatei 'SYSFILE.TOY' besteht aus drei Teilen :
-
- - den Namen und Stelligkeiten bestimmter Funktoren, die vom
- inneren Interpreter für besondere Aufgaben benötigt werden.
- Es sind ';' und ',' (benötigt für die Implementierung des
- 'cut'), 'tag' und 'call', '[]' und '.', 'error' (für die
- Behandlung von Aufruffehlern), 'user' (für die Ein-/Ausgabe),
- die Operatortypen und 'ear' (das Ziel, das vom inneren
- Interpreter aufgerufen wird).
- Die Beschreibungen dieser Funktoren sollten nicht verändert
- werden; ausgenommen davon ist 'ear', das geändert werden
- kann, um ein anderes Ziel vom inneren Interpreter aus
- aufrufen zu lassen.
-
- - den Namen und Stelligkeiten der Systemfunktionen. Die Namen
- der Systemfunktionen können beliebig geändert werden, aber
- die Stelligkeiten müssen erhalten bleiben. Wird der Name
- einer Systemfunktion geändert, so muß die Änderung in allen
- Programmen, insbesondere im äußeren Interpreter, durchgeführt
- werden; andernfalls sind Programme, die die betreffende
- Funktion benutzen, nicht mehr lauffähig !
-
- - der Systembibliothek. Diese enthält (in der Syntax des
- inneren Interpreters) die Definitionen der vordefinierten
- Prädikate und den Zwischencode des äußeren Interpreters. Auch
- hier gilt für Namensänderungen das oben gesagte; Änderungen
- der Definitionen haben nicht so weitreichende Folgen, aber
- sie können durchaus dazu führen, daß Programme
- (einschließlich der Hilfsprogramme) nicht mehr lauffähig
- sind. Zu Veränderungen an der Benutzerschnittstelle wird im
- Abschnitt A.4 noch näheres gesagt.
-
- Die Beschreibungen der Spezialfunktoren und Systemfunktionen
- werden zur Initialisierung des inneren Interpreters verwendet; sie
- werden eingelesen, nachdem AES, VDI und die Speicherbereiche des
- Interpreters initialisiert wurden.
- Die Systembibliothek wird direkt nach der Initialisierung des
- inneren Interpreters eingelesen; am Dateiende steht ein 'seen', so
- daß nach dem Einlesen der äußere Interpreter gestartet wird.
-
-
- A.4 Die Implementierung der Benutzerschnittstelle
-
- Die Syntax des inneren Interpreters ist zwar sehr einfach, dafür
- sind Programme in dieser Form nur schwer verständlich; ein
- Programm von der Größenordnung des äußeren Interpreters kann daher
- nicht direkt im Zwischencode entwickelt werden.
- Aus diesem Grund wurde die Benutzerschnittstelle in einer
- Untermenge der zu implementierenden Sprache geschrieben. Diese
- "Halbsprache" ist in folgenden Punkten gegenüber der vollständigen
- Syntax eingeschränkt:
-
- - Operatornotation und die Verwendung von grammatischen Regeln
- ist nicht erlaubt.
- - Die Listennotation ist leicht eingeschränkt : In einem Term
- der Form
-
- [ A, B, C ... | X ]
-
- muß X eine Variable sein.
- - Das Komma in einer Regel und das Symbol ':-' werden als
- Trennzeichen (nicht als Operatoren) behandelt. ';' darf in
- einer Regel nicht als Trennzeichen, wohl aber als Funktor
- verwendet werden.
-
- Das Hilfsprogramm 'BOOTER.TOY' kann diese Notation praktisch 1 : 1
- in den Zwischencode übersetzen.
-
- Der Quellcode der Benutzerschnittstelle befindet sich in der Datei
- 'MONITOR.PRO'; nach der Übersetzung sollte man aus dem
- entstandenen Zwischencode alle Kommentare entfernen, da diese
- ziemlich viel Platz verbrauchen. Dabei ist zu beachten, daß manche
- Prädikate, die Kommentare erkennen oder erzeugen (in der
- vorliegenden Version sind es 'skip', 'absorbtoken' und
- 'nextline'), das Zeichen '%' benutzen; man darf also nicht einfach
- alle Zeilen löschen, in denen '%' vorkommt.
-
- Über die Verfahren, die beim Entwurf des äußeren Interpreters
- angewandt wurden, und über dessen Aufbau, kann hier nichts gesagt
- werden; eine ausführliche Beschreibung findet sich in "Prolog for
- Programmers".
-
-
- A.5 Unterschiede zur Dokumentation
-
- In der vorliegenden Version 3.3 gibt es folgende Unterschiede zu
- dieser Dokumentation:
-
- - Die Betätigung der Tasten 'Control' 'C' führt in vielen
- Fällen zum sofortigen Abbruch des äußeren Interpreters. Das
- Programm verhält sich so, als ob nach einer Unterbrechung mit
- 'Shift' 'Alternate' 'Help' die Option A (Abbruch) gewählt
- wurde.
- Der innere Interpreter wird nicht abgebrochen; wird gerade
- keine Datei eingelesen, so wird der äußere Interpreter wieder
- gestartet.
-
- - Falls bei einer Diskettenoperation ein kritischer Fehler
- (Wechsel der Diskette, falsche Diskette im Laufwerk etc.)
- auftritt, erfolgt die Meldung:
-
- There was a critical error. (A)bort, (R)etry or (I)gnore ?
-
- Die Eingabe von 'A' führt zum Abbruch (mit einer
- Fehlermeldung); 'R' veranlaßt einen neuen Versuch, und bei
- 'I' wird der Fehler ignoriert (Vorsicht !).
-
- - Die Anzeige der Teilziele im Testmodus ("CALL", "REDO",
- "EXIT", "FAIL") funktioniert (noch) nicht richtig. "FAIL"
- wird bei jedem Mißerfolg, auch vor einem 'backtrack',
- angezeigt, nicht nur (wie es richtig wäre) nach dem
- endgültigen Fehlschlag des Teilzieles. Im Gegensatz dazu wird
- "EXIT" nicht bei allen erfolgreich erfüllten Zielen
- angezeigt.
- Es ist zweifelhaft, ob diese Mißstände noch behoben werden
- (können ?). Der "FAIL"-Fehler ist beim Programmtest
- hinderlich und wird wahrscheinlich noch ausgemerzt, aber der
- "EXIT"-Fehler ist teilweise durch die optimierte (!)
- Ausführung von rekursiven Prädikaten bedingt und kann -
- zumindest in dieser Situation - nicht verhindert werden.
- (TOY Prolog führt eine 'tail recursion optimisation' (TRO)
- durch, d.h., daß die 'activation records' von Prädikaten
- zerstört werden können, falls dadurch Speicher gespart wird.
- Der Name kommt von rekursiven Prädikaten, bei denen der
- rekursive Aufruf der letzte in seiner Klausel ist; allerdings
- erstreckt sich die TRO auch auf andere Situationen, wie z.B.
- den 'cut')
-
-
- - Es wurden drei weitere Systemfunktionen implementiert, die
- auf die Dateiverzeichnisse des Betriebssystems zugreifen :
-
- disk_dir (VAR)
- instantiiert PAR_1 mit dem Namen des aktuellen
- Dateiverzeichnisses, d.h. mit der Laufwerksbezeichnung und
- dem Pfadnamen.
-
- disk_dir (NAME)
- macht das durch PAR_1 angegebene Dateiverzeichnis zum
- aktuellen Dateiverzeichnis. Die Laufwerksbezeichnung kann
- fehlen; in diesem Fall wird das aktuelle Laufwerk benutzt.
- Ist PAR_1 fehlerhaft, so wird ein Systemaufruffehler erzeugt.
-
- disk_search (NAME, INTEGER, TERM, TERM)
- PAR_1 und PAR_2 sind Parameter für den Betriebssystemaufruf
- F_SFIRST : Es wird nach der ersten Datei im aktuellen
- Dateiverzeichnis (oder in einem Verzeichnis, das durch einen
- in PAR_1 vorhandenen Pfadnamen bestimmt wird) gesucht, die
- dem Suchmuster in PAR_1 entspricht, und deren Attribute dem
- Suchattribut PAR_2 entsprechen. Das Suchmuster wird wie ein
- Dateiname angegeben; allerdings können hier die 'wild cards'
- * und ? benutzt werden. Im Pfadnamen dürfen keine 'wild
- cards' stehen.
- Die Suchattribute werden in PAR_2 bitweise angegeben; im
- einzelnen bedeutet
-
- 0 Normaler Dateizugriff möglich
- 1 Datei ist schreibgeschützt
- 2 Datei ist 'versteckt'
- 4 Datei ist 'Systemdatei' (ebenfalls versteckt)
- 8 keine Datei, sondern der Name der Diskette
- 16 keine Datei, sondern Dateiverzeichnis
- 32 Datei wurde beschrieben und geschlossen (???)
-
- Falls keine entsprechende Datei gefunden wurde, schlägt der
- Aufruf fehl; ansonsten wird versucht, PAR_3 mit dem Namen und
- PAR_4 mit den Attributen der gefundenen Datei zu unifizieren.
-
- disk_search (TERM, TERM)
- sucht nach der nächsten Datei, deren Name und Attribute zu
- den im letzten Aufruf von disk_search/4 angegebenen
- Suchmustern passen, und versucht, PAR_3 mit dem Dateinamen
- und PAR_4 mit den zugehörigen Attributen zu unifizieren.
- Falls keine passende Datei mehr gefunden wird, schlägt der
- Aufruf fehl.
-
-
- - Die Eingabe von der Tastatur (Datenströme 'user' und 'keybd')
- wurde verändert. Insbesondere werden die Funktionstasten (F1
- bis F10 und der Cursorblock) jetzt ausgenutzt.
- Es besteht die Möglichkeit, die Funktionstasten mit
- Zeichenketten zu belegen, die beim Betätigen der
- entsprechenden Tasten so interpretiert werden, als ob sie von
- der Tastatur aus eingegeben wurden.
- Dazu dient die neue Systemfunktion
-
- set_fstring (INTEGER, NAME).
- PAR_1 muß eine Integerzahl aus dem Bereich von 0 bis 27 sein,
- die die gewünschte Funktionstaste auswählt (s.u.). Die
- ausgewählte Funktionstaste wird mit einer Zeichenkette
- belegt, die durch den Namen von PAR_2 gegeben ist (PAR_2 muß
- ein Funktor ohne Argumente sein).
-
- Die Funktionstasten sind wie folgt gekennzeichnet:
-
- 0 F1 10 Shift/F1 20 Clr/Home
- 1 F2 11 Shift/F2 21 Cursor hoch
- 2 F3 12 Shift/F3 22 Cursor links
- 3 F4 13 Shift/F4 23 Cursor rechts
- 4 F5 14 Shift/F5 24 Cursor runter
- 5 F6 15 Shift/F6 25 Insert
- 6 F7 16 Shift/F7 26 Undo
- 7 F8 17 Shift/F8 27 Help
- 8 F9 18 Shift/F9
- 9 F10 19 Shift/F10
-
- Für die Zeichenkette gilt noch folgende Besonderheit :
- Steht in der Zeichenkette ein '\', so wird das nachfolgende
- Zeichen so interpretiert, als ob die entsprechende Taste
- zusammen mit 'Control' gedrückt worden wäre.
- Ausnahme : Ist das folgende Zeichen wieder ein '\', so gilt
- es (wie üblich) als ein einzelnes '\'.
-
- Beispiele : \G - 'Bell', \H - 'Backspace', \M - 'Return'.
-
-
- Geplante Änderungen :
-
- - Fehler im Testmodus, siehe oben.
-
- - Einbindung von Programmen aus anderen Sprachen (C, Pascal,
- Assembler).
-
- (Falls ich jemals dazu komme, mir dafür einen Grund und eine
- Vorgehensweise zu überlegen ...)
-
- Ende des Anhangs zur Dokumentation von TOY Prolog ST, Version 3
-
-